﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using iTelluro.Explorer.Domain.Seedwork.Specification;

namespace iTelluro.Explorer.Domain.Seedwork
{
    /// <summary>
    /// Base interface for implemnet a "Repository Pattern"
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public interface IRepository<TEntity> : IDisposable
        where TEntity : Entity
    {
        /// <summary>
        /// Get the unit of work in this repository
        /// </summary>
        IUnitOfWork UniteOfWork { get; }

        /// <summary>
        /// Add item into repository
        /// </summary>
        /// <param name="item">Item to add to repository</param>
        void Add(TEntity item);

        /// <summary>
        /// Delete item
        /// </summary>
        /// <param name="item">Item to delete</param>
        void Remove(TEntity item);

        /// <summary>
        /// Set item as modified
        /// </summary>
        /// <param name="item">Item to modify</param>
        void Modify(TEntity item);

        /// <summary>
        /// Track entity into this repository,really in UnitOfWork.
        /// </summary>
        /// <param name="item"></param>
        void TrackItem(TEntity item);

        /// <summary>
        /// Set modified entity into the repository.
        /// when calling Commit() method in UnitOfWork 
        /// these changes will be saved into the storage
        /// </summary>
        /// <param name="persisted">The persisted item</param>
        /// <param name="currrent">The current item</param>
        void Merge(TEntity persisted, TEntity currrent);

        /// <summary>
        /// Get element by entity key
        /// </summary>
        /// <param name="id">Entity key value</param>
        /// <returns></returns>
        TEntity Get(string id);

        TEntity Get(decimal id);

        TEntity Get(int id);
        /// <summary>
        /// Get all elements of type TEntity in repository
        /// </summary>
        /// <returns>List of selected elements</returns>
        IEnumerable<TEntity> GetAll();

        /// <summary>
        /// Get all elements of type TEntity that matching a specification
        /// </summary>
        /// <param name="specification">Specification that result meet</param>
        /// <returns></returns>
        IEnumerable<TEntity> AllMatching(ISpecification<TEntity> specification);

        /// <summary>
        /// Get all element of type TEntity in repository
        /// </summary>
        /// <typeparam name="KProperty">Page index</typeparam>
        /// <param name="pageIndex">Number of elements in each page</param>
        /// <param name="pageCount">Order by expression for this query</param>
        /// <param name="orderByExpression">Specify if order is ascending</param>
        /// <param name="ascending">List of selected elements</param>
        /// <returns></returns>
        IEnumerable<TEntity> GetPaged<KProperty>(int pageIndex, int pageCount, Expression<Func<TEntity, KProperty>> orderByExpression, bool ascending);

        /// <summary>
        /// Get elements of type TEntity in repository
        /// </summary>
        /// <param name="filter">Filter that each element do match</param>
        /// <returns>List of selected elements</returns>
        IEnumerable<TEntity> GetFiltered(Expression<Func<TEntity, bool>> filter);

        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <typeparam name="KProperty"></typeparam>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageCount">页条数</param>
        /// <param name="specification">条件规约</param>
        /// <param name="orderByExpression">排序条件</param>
        /// <param name="ascending">排序</param>
        /// <returns></returns>
        IEnumerable<TEntity> GetPaged<KProperty>(int pageIndex, int pageCount, ISpecification<TEntity> filterSpecification, Expression<Func<TEntity, KProperty>> orderByExpression, bool ascending);
        int GetRecordCount(Domain.Seedwork.Specification.ISpecification<TEntity> filterSpecification);
    }
}
